package com.xiao.androidcompose01.screen

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.koinScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import com.xiao.androidcompose01.LocalInnerPadding
import com.xiao.androidcompose01.api.NetResponse
import com.xiao.androidcompose01.api.data.AccountData
import com.xiao.androidcompose01.file.AccountFileUtil
import com.xiao.androidcompose01.ui.theme.BackgroundColor
import com.xiao.androidcompose01.ui.theme.MainColor
import com.xiao.androidcompose01.utils.StringUtils.isPhone
import com.xiao.androidcompose01.weight.LoadingAnim
import com.xiao.androidcompose01.weight.MainButton
import com.xiao.androidcompose01.weight.MainButtonState
import com.xiao.androidcompose01.weight.PasswordInputField
import com.xiao.androidcompose01.weight.PhoneInputField
import com.xiao.libcore.result.withXResult
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.forms.submitForm
import io.ktor.http.Parameters
import kotlinx.coroutines.launch
import org.koin.core.annotation.Factory
import org.koin.core.annotation.Module
import org.koin.core.context.startKoin
import org.koin.ksp.generated.defaultModule

/**
 * 登录页面
 */
class LoginScreen : Screen {
   
   @Composable
   override fun Content() {
      val paddingValues = LocalInnerPadding.current ?: PaddingValues()
      val navigator = LocalNavigator.current
      val accountLoginModel = koinScreenModel<AccountLoginModel>()
      val checkerAccountState by accountLoginModel.state.collectAsStateWithLifecycle()
      var passwordTip by remember { mutableStateOf("") }
      LaunchedEffect(checkerAccountState) {
         when (checkerAccountState) {
            is AccountLoginModel.State.Tip -> {
               passwordTip = (checkerAccountState as AccountLoginModel.State.Tip).tip
            }
            
            is AccountLoginModel.State.Success -> {
               //登录成功了
               passwordTip = ""
               val accountData = (checkerAccountState as AccountLoginModel.State.Success).accountData
               navigator?.replace(MainScreen(accountData))
            }
            
            else -> {
               passwordTip = ""
            }
         }
      }
      if (checkerAccountState is AccountLoginModel.State.AutoLogin) {
         Box(
            modifier = Modifier
               .fillMaxSize()
               .background(BackgroundColor)
               .padding(paddingValues)
               .padding(horizontal = 24.dp),
            contentAlignment = Alignment.Center
         ){
            LoadingAnim(modifier = Modifier.size(80.dp).alpha(1f))
         }
      }else{
         Column(
            modifier = Modifier
               .fillMaxSize()
               .background(BackgroundColor)
               .padding(paddingValues)
               .padding(horizontal = 24.dp)
         ) {
            Spacer(modifier = Modifier.weight(0.4f))
            Row(
               modifier = Modifier.align(Alignment.CenterHorizontally),
               verticalAlignment = Alignment.CenterVertically
            ) {
               Text(
                  "LOGO", color = MainColor, fontWeight = FontWeight.SemiBold, fontSize = 24.sp,
                  style = TextStyle(fontStyle = FontStyle.Italic)
               )
            }
            PhoneInputField("请输入手机号", onChange = {
               accountLoginModel.changePhone(it)
            }, modifier = Modifier.padding(top = 30.dp))
            PasswordInputField("请输入密码", onChange = {
               accountLoginModel.changePassword(it)
            }, modifier = Modifier.padding(top = 10.dp))
            Text(
               passwordTip, color = Color(0xFFff0000), fontWeight = FontWeight.SemiBold,
               fontSize = 14.sp, modifier = Modifier
                  .padding(start = 12.dp, top = 10.dp)
                  .alpha(if (passwordTip.isBlank()) 0f else 1f)
            )
            MainButton(
               "登录",
               modifier = Modifier
                  .fillMaxWidth()
                  .padding(horizontal = 20.dp)
                  .padding(top = 30.dp),
               state = if (checkerAccountState is AccountLoginModel.State.Loading) {
                  MainButtonState.LOADING
               } else MainButtonState.ENABLE
            ) {
               if (accountLoginModel.checker()) {
                  accountLoginModel.login()
               }
            }
            Spacer(modifier = Modifier.weight(1f))
         }
      }
      
   }
   
   @Preview
   @Composable
   private fun ContentPreview() {
      startKoin {
         modules(defaultModule)
      }
      CompositionLocalProvider(LocalNavigator provides null) {
         Content()
      }
      
   }
}


@Module
@Factory
class AccountLoginModel(
   val httpClient: HttpClient,
   val accountFileUtil: AccountFileUtil
) : StateScreenModel<AccountLoginModel.State>(State.Init)
   {
   
   private val phone = mutableStateOf("")
   private val password = mutableStateOf("")
   
   
   init {
      val account = accountFileUtil.loadAccount()
      if (account != null) {
         mutableState.value = State.AutoLogin
         phone.value = account.phone
         password.value = account.password
         login()
      } else {
         mutableState.value = State.Init
      }
   }
   
   sealed class State {
      object Init : State()
      data class Tip(val tip: String) : State()
      object AutoLogin : State()
      object Loading : State()
      data class Success(val accountData: AccountData) : State()
   }
   
   fun changePhone(phone: String) {
      mutableState.value = State.Init
      this.phone.value = phone
   }
   
   fun changePassword(password: String) {
      mutableState.value = State.Init
      this.password.value = password
   }
   
   fun checker(): Boolean {
      mutableState.value = State.Init
      val phone = phone.value
      val password = password.value
      if (phone.isBlank()) {
         mutableState.value = State.Tip("请输入手机号")
         return false
      }
      if (!phone.isPhone()) {
         mutableState.value = State.Tip("手机号格式不正确")
         return false
      }
      if (password.isEmpty()) {
         mutableState.value = State.Tip("请输入密码")
         return false
      }
      return true
   }
   
   fun login() {
      val phone = phone.value
      val password = password.value
      screenModelScope.launch {
         withXResult {
            mutableState.value = State.Loading
            httpClient.submitForm(
               url = "/mobile/login",
               formParameters = Parameters.build {
                  append("username", phone)
                  append("password", password)
               }
            ).body<NetResponse<AccountData>>().requestData()
         }.ifError {
            mutableState.value = State.Tip(it.message())
         }.ifSuccess {
            accountFileUtil.saveAccount(phone, password,it.sessionId)
            mutableState.value = State.Success(it)
         }
         
      }
   }
   
   override fun onDispose() {
      println("退出了ViewModel:${password.value}")
      super.onDispose()
   }
   
}
